﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Diagnostics;



namespace BikePartsManager
{
    class DataBase
    {
        #region Attributes

        private int _idCounter = 0;
        private List<User> _users;
        private string _defaultFile = ".\\XML_proto.xml";
        private static DataBase instance;


        #endregion

        #region Methods

        public DataBase()
        {
            _users = new List<User>();
        }

        public bool LoadDatabaseFile()
        {
            return LoadDatabaseFile(_defaultFile);
        }

        public bool LoadDatabaseFile(string pathFile)
        {
            try
            {

                //Debug
                ConsoleManager.Show();
                Console.WriteLine("Start Loading...\n");

                XElement xelement = XElement.Load(pathFile);

                IEnumerable<XElement> users = xelement.Elements();
                foreach (var user in users)
                {
                    Console.WriteLine("New user !");
                    User tempUser = new User();

                    //User Informations
                    tempUser.Name = user.Element("Name").Value;
                    tempUser.FirstName = user.Element("FirstName").Value;
                    tempUser.Birthday = DateTime.ParseExact(user.Element("Birthday").Value, "dd/MM/yyyy", null);

                    if (user.Element("Gender").Value == "MALE")
                        tempUser.Gender = UserGender.MALE;
                    else if (user.Element("Gender").Value == "FEMELLE")
                        tempUser.Gender = UserGender.FEMELLE;
                    else
                        tempUser.Gender = UserGender.UNKNOWN;

                    tempUser.PicturePath = user.Element("Picture").Value;


                    //Debug
                    Console.WriteLine("-- User Info --");
                    Console.WriteLine("Name : " + tempUser.Name);
                    Console.WriteLine("FirstName : " + tempUser.FirstName);
                    Console.WriteLine("Birthday : " + tempUser.Birthday);
                    Console.WriteLine("Gender : " + tempUser.Gender.ToString());
                    Console.WriteLine("PicturePath : " + tempUser.PicturePath);

                    //BikeInformations
                    IEnumerable<XElement> bikes = user.Elements("Bike");
                    foreach (var bike in bikes)
                    {
                        Bike bikeTemp = new Bike();

                        bikeTemp.Brand = bike.Element("Brand").Value;
                        bikeTemp.Model = bike.Element("Model").Value;

                        switch (bike.Element("Type").Value)
                        {
                            case "ROADSTER": bikeTemp.Type = BikeType.ROADSTER; break;
                            case "ROUTIERE": bikeTemp.Type = BikeType.ROUTIERE; break;
                            case "SPORTIVE": bikeTemp.Type = BikeType.SPORTIVE; break;
                            case "TRAIL": bikeTemp.Type = BikeType.TRAIL; break;
                            case "SUPERMOTARD": bikeTemp.Type = BikeType.SUPERMOTARD; break;
                            case "ENDURO": bikeTemp.Type = BikeType.ENDURO; break;
                            case "GT": bikeTemp.Type = BikeType.GT; break;
                            case "OTHER": bikeTemp.Type = BikeType.OTHER; break;
                            default: bikeTemp.Type = BikeType.OTHER; break;
                        }

                        bikeTemp.Cylinder = int.Parse(bike.Element("Cylinder").Value);
                        bikeTemp.Production_date = DateTime.ParseExact(bike.Element("DateProd").Value, "dd/MM/yyyy", null);
                        bikeTemp.Buy_date = DateTime.ParseExact(bike.Element("DateBuy").Value, "dd/MM/yyyy", null);
                        bikeTemp.Insurance = int.Parse(bike.Element("InsurancePrice").Value);
                        bikeTemp.Argus = int.Parse(bike.Element("Argus").Value);
                        bikeTemp.Infos = bike.Element("Infos").Value;

                        if (bike.Element("BuyType").Value == BuyType.NEUF.ToString())
                            bikeTemp.Buy_Type = BuyType.NEUF;
                        else if (bike.Element("BuyType").Value == BuyType.OCCASION.ToString())
                            bikeTemp.Buy_Type = BuyType.OCCASION;
                        else
                            bikeTemp.Buy_Type = BuyType.OTHER;


                        //Debug
                        Console.WriteLine("--- Bike Info ---");
                        Console.WriteLine(" Brand : " + bikeTemp.Brand);
                        Console.WriteLine(" Model : " + bikeTemp.Model);
                        Console.WriteLine(" Type : " + bikeTemp.Type);
                        Console.WriteLine(" Cylinder : " + bikeTemp.Cylinder);
                        Console.WriteLine(" Prod date : " + bikeTemp.Production_date);
                        Console.WriteLine(" Buy date : " + bikeTemp.Buy_date);
                        Console.WriteLine(" Insurance : " + bikeTemp.Insurance);
                        Console.WriteLine(" Argus : " + bikeTemp.Argus);
                        Console.WriteLine(" Infos : " + bikeTemp.Infos);
                        Console.WriteLine(" BuyType : " + bikeTemp.Buy_Type);



                        //Pars Informations
                        IEnumerable<XElement> parts = bike.Elements("Part");
                        foreach (var part in parts)
                        {
                            Part tempPart = new Part();

                            tempPart.Brand = part.Element("Brand").Value;
                            tempPart.Name = part.Element("Name").Value;
                            tempPart.Price = int.Parse(part.Element("Price").Value);
                            tempPart.Info = part.Element("Info").Value;

                            if (part.Element("BuyType").Value == BuyType.NEUF.ToString())
                                tempPart.BuyType = BuyType.NEUF;
                            else if (part.Element("BuyType").Value == BuyType.OCCASION.ToString())
                                tempPart.BuyType = BuyType.OCCASION;
                            else
                                tempPart.BuyType = BuyType.OTHER;


                            //Debug
                            Console.WriteLine("---- Part Info ---");
                            Console.WriteLine("  Brand : " + tempPart.Brand);
                            Console.WriteLine("  Name : " + tempPart.Name);
                            Console.WriteLine("  Price : " + tempPart.Price);
                            Console.WriteLine("  Info : " + tempPart.Info);
                            Console.WriteLine("  BuyType : " + tempPart.BuyType);

                            //Add parts
                            bikeTemp.AddParts(tempPart.Name, tempPart.Brand, tempPart.Info, tempPart.Price, tempPart.BuyType);
                        }

                        //Add Bike
                        tempUser.AddBike(bikeTemp.Brand, bikeTemp.Model, bikeTemp.Type, bikeTemp.Cylinder, bikeTemp.Production_date, bikeTemp.Buy_date, bikeTemp.Insurance, bikeTemp.Argus, bikeTemp.Infos, bikeTemp.Buy_Type);
                    }

                    //Add into Db
                    this.AddUser(tempUser.Name, tempUser.FirstName, tempUser.Birthday, tempUser.Gender, tempUser.PicturePath);
                }

            }
            catch (Exception e)
            {
                //Console.WriteLine("------------- ERROR ----------------- \n" + e.ToString() + "\n");
                return false;
            }


            return true;
        }


        #endregion

        #region Getter & Setter

        public int AddUser(string Name, string FirstName, DateTime BirthDay, UserGender Gender, string PicturePath)
        {
            int id = _idCounter;
            _idCounter++;

            User u = new User();

            u.Name = Name;
            u.FirstName = FirstName;
            u.Birthday = BirthDay;
            u.Gender = Gender;
            u.PicturePath = PicturePath;
            u.Id = id;

            _users.Add(u);

            return id;
        }

        public void DeleteUser(int Id)
        {
            for(int it = 0; it < _users.Count; it++)
            {
                if (_users[it].Id == Id)
                {
                    _users.RemoveAt(it);
                    break;
                }
            }
        }

        public void ModifyUser(int UserID, string FirstName, string LastName, DateTime Birthday, UserGender Gender, string Avatar)
        {
            for (int it = 0; it < _users.Count; it++)
            {
                if (_users[it].Id == UserID)
                {
                    _users[it].Name = LastName;
                    _users[it].FirstName = FirstName;
                    _users[it].Birthday = Birthday;
                    _users[it].Gender = Gender;
                    _users[it].PicturePath = Avatar;
                    break;
                }
            }
        }

        public List<int> GetUsers()
        {
            List<int> temp = new List<int>();

            for (int it = 0; it < _users.Count; it++)
                temp.Add(_users[it].Id);
            return temp;
        }

        public User GetInfosUser(int UserID)
        {
            for (int it = 0; it < _users.Count; it++)
            {
                if (_users[it].Id == UserID)
                    return _users[it];
            }
            return new User();
        }

        public List<User> Users
        {
            get { return _users; }
            set { _users = value; }
        }

        public static DataBase Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new DataBase();
                }
                return instance;
            }
        }
        #endregion
    }
}
